#ifndef __UPGRADE_DOUBLE_FLASH_H__
#define __UPGRADE_DOUBLE_FLASH_H__

#include "upgrade_cfg.h"

#if 1 == UPGRADE_DOUBLE_FLASH_MODE

#include <stdint.h>

typedef struct Upgrade_Info{
    uint8_t u8CurApp;
    uint8_t u8NeedUpgrade;
    // 后续扩展校验信息等
    uint16_t u16Reserved; 
} Upgrade_Info_t;

#endif

// 双flash模式下，bootloader的接口定义
#if 1 == UPGRADE_DOUBLE_FLASH_MODE && 1 == BOOTLOADER

typedef struct Bootloader {

    struct {

        /**
        * @brief 跳转到指定地址
        * @param u32Address 跳转地址
        * @return none
        */
        void    
        (*pfnJumpTo)(uint32_t u32Address);

        /**
        * @brief 写信息 -- 掉电保存
        * @param u32Addr 写地址
        * @param pu8Data 写数据指针
        * @param u32Len 写长度
        * @return 0:成功; 其他:失败
        */
        uint8_t 
        (*pfnInfoWrite)(uint32_t u32Addr, uint8_t* pu8Data, uint32_t u32Len);
        
        /**
        * @brief 读信息 -- 掉电保存
        * @param u32Addr 读地址
        * @param pu8Data 读数据指针
        * @param u32Len 读长度
        * @return 0:成功; 其他:失败
        */
        uint8_t 
        (*pfnInfoRead)(uint32_t u32Addr, uint8_t* pu8Data, uint32_t u32Len);
    } HW;

    struct {
        uint8_t u8Init;         // 是否初始化
        uint8_t u8Reserved;
        uint16_t u16Reserved;
        Upgrade_Info_t stInfo;  // 升级信息
    } SW;

} Bootloader_t;

/**
 * @brief bootloader 初始化
 * @param pstBootloader 指向bootloader结构体的指针
 * @return 0:成功; 其他:失败
 */
Upgrade_Ret_t 
bootloader_init(Bootloader_t* pstBootloader);

/**
 * @brief bootloader 运行
 * @return 0:成功; 其他:失败
 */
Upgrade_Ret_t
Bootloader_run(void);

#endif

// 双flash模式下，app的接口定义
#if 1 == UPGRADE_DOUBLE_FLASH_MODE && 1 == UPGRADE_APP

typedef struct UpgradeApp {

    struct {

        /**
         * @brief 重启
         * @return none
         */
        void    
        (*pfnRestart)(void);

        /**
         * @brief 写信息 -- 掉电保存
         * @param u32Addr 写地址
         * @param pu8Data 写数据指针
         * @param u32Len 写长度
         * @return 0:成功; 其他:失败
         */
        uint8_t 
        (*pfnInfoWrite)(uint32_t u32Addr, uint8_t* pu8Data, uint32_t u32Len);
        
        /**
         * @brief 读信息 -- 掉电保存
         * @param u32Addr 读地址
         * @param pu8Data 读数据指针
         * @param u32Len 读长度
         * @return 0:成功; 其他:失败
         */
        uint8_t 
        (*pfnInfoRead)(uint32_t u32Addr, uint8_t* pu8Data, uint32_t u32Len);

        /**
         * @brief 写固件函数 -- 内部flash操作
         * @param u32Addr 写地址
         * @param pu8Data 写数据指针
         * @param u32Len 写长度
         * @return 0:成功; 其他:失败
         */
        uint8_t 
        (*pfnDataWrite)(uint32_t u32Addr, uint8_t* pu8Data, uint32_t u32Len);
        
    } HW;

    struct {
        uint8_t u8Init;         // 是否初始化
        uint8_t u8Reserved;
        uint16_t u16Reserved;
        uint32_t u32FWAddr;     // 固件地址
        Upgrade_Info_t stInfo;  // 升级信息
    } SW;

} UpgradeApp_t;

/**
 * @brief upgrade app 初始化
 * @param pstUpgradeApp 指向app结构体的指针
 * @return 0:成功; 其他:失败
 */
Upgrade_Ret_t 
upgrade_app_init(UpgradeApp_t* pstUpgradeApp);

/**
 * @brief upgrade app 运行
 * @return 0:成功; 其他:失败
 */
Upgrade_Ret_t
upgrade_app_run(void);

/**
 * @brief 保存固件
 * @param pu8Data 固件数据指针
 * @param u32Len 固件数据长度
 * @return 0:成功; 其他:失败
 */
Upgrade_Ret_t
upgrade_app_save(uint8_t* pu8Data, uint32_t u32Len);

#endif

#endif /* __UPGRADE_DOUBLE_FLASH_H__ */
